using System.Web;

using System.Xml;
using System;

/*	-----------------------------------------------------------------------	
	Copyright:	umlungu consulting (pty) ltd
	Author:		Alan Benington	
	Started:	2006-03-08	
	Status:		release	
	Version:	2.0.0
	Build:		20080401
	License:	GNU General Public License
	-----------------------------------------------------------------------	*/

/*	-----------------------------------------------------------------------	
	Development Notes:
	==================
	20080401:	Minor modifications for performance profiling
	-----------------------------------------------------------------------	*/
	
namespace umlungu.engineX.blogX {
	/// <summary>
	/// Description of the x_form class.
	/// <para>This is a 'lite' version of the xml form object code (originally from the asp form handling mechanism).</para>
	/// <para>Form handling works as follows:</para>
	/// <para> - A form is defined in the xml source of the content in a 'form' element that contains one or more 'fld' elements</para>
	/// <para> - Data is pre-populated into the field within this object from application or session state</para>
	/// <para> - The form is rendered by the xsl using the 'type' attributes to determine the html form field type</para>
	/// <para>This 'lite' version differs from the original as follows:</para>
	/// <para> - all fld attributes and child elements are defined within the xml</para>
	/// <para> - no Application definition of fields (ie like formobjs.xml), the profileX.xml serves this role as well</para>
	/// <para> - 'wf_obj' attribute is replaced by 'type'</para>
	/// <para> - only data is pre-poulated (not other properties from an application definition)</para>
	/// <para></para>
	/// </summary>
	public class x_form : x_actor {
		#region Invisible properties
		#endregion

		#region Visible properties
		#endregion

		#region Constructors/Destructors
		/// <overloads>Constructor</overloads>
		/// <summary>Default constructor</summary>
		/// <param name="thispage">The web application Page object</param>
		public x_form(displayX thispage) : base(thispage) {
		}
		/// <summary>Constructor description</summary>
		/// <param name="thispage">The web application Page object</param>
		/// <param name="form">The XmlElement 'form' within the content document</param>
		public x_form(displayX thispage, XmlElement form) : this(thispage) {
			Load(form);
		}
		#endregion

		#region Public methods
		/// <summary>
		///	Create the XML for transformation by:					
		///	- adding nodes from the object definitiions to the form XML (not now)
		///	- adding the data (pre-population) to the form XML
		/// </summary>
		/// <param name="form">The XmlElement 'form' within the content document</param>
		public void Load(XmlElement form) {
			Debugger.Spoor("addFormData", "form");
			addIDs(form);
			addObjs();
			addRef();
			addFormData(form);
		}
		/// <summary>
		///	Create the XML for transformation by:					
		///	- adding nodes from the object definitiions to the form XML (not now)
		///	- adding the data (pre-population) to the form XML
		/// </summary>
		/// <param name="content">The content document that contains 'fld' elements</param>
		public void Load(XmlDocument content) {
			Debugger.Spoor("addFormData", "content");
			addIDs(content);
			addObjs();
			addRef();
			addFormData(content);
		}
		#endregion
		
		#region Protected methods
		#endregion
				
		#region Private methods
		/// <summary>
		/// AddIDs:: Add nodes from the wf_objs to the form XML
		/// </summary>
		private void addIDs(XmlDocument contentDoc) {
			addIDs(contentDoc.DocumentElement.SelectNodes("//fld"));
		}
		private void addIDs(XmlElement formElem) {
			addIDs(formElem.SelectNodes("fld"));
		}
		private void addIDs(XmlNodeList fldlist) {
			XmlElement fld;
			int i = 0;
			foreach (XmlNode fldnode in fldlist) {
				fld = (XmlElement) fldnode;
				i++;
				// Add the id attribute
				fld.SetAttribute("id", i.ToString());
				if (fld.GetAttribute("name") == "")
					fld.SetAttribute("name", String.Concat("xfld_", i.ToString()));
			}
		}
		private void addObjs() {
			// do nothing for now
		}
		private void addRef() {
			// do nothing for now
		}
		/// <summary>
		/// AddFormData:: Add the data (pre-population) to the form XML from the profile(s).
		/// </summary>
		private void addFormData(XmlDocument contentDoc) {
			Debugger.Spoor("addFormData", "XmlDocument");
			addFormData(contentDoc.DocumentElement.SelectNodes("//fld"));
		}	
		private void addFormData(XmlElement formElem) {
			//Debugger.Spoor("addFormData", "XmlElement");
			if (formElem == null)
				return;
			addFormData(formElem.SelectNodes("descendant::fld"));
		}	
		private void addFormData(XmlNodeList fldlist) {
			//Debugger.Spoor("addFormData", "XmlNodeList");
			XmlElement fld;
			foreach (XmlNode fldnode in fldlist) {
				fld = (XmlElement) fldnode;
				//Debugger.Spoor("addFormData", "fld", fld.GetAttribute("name"));
				addProfileValue(fld);
				addSubObjFromProfile(fld);
			}
		}	
		/// <summary>
		/// addProfileValue:: pre-populates the field value from the profile
		/// </summary>
		private void addProfileValue(XmlElement fld) {
			XmlNode val, profnode = getProfileNode(fld.GetAttribute("name"));
			if (profnode != null){
				val = fld.SelectSingleNode("value");
				if (val != null)
					if (((XmlElement)val).GetAttribute("force") != "yes")
						val.InnerText = profnode.InnerText;
			}
		}	
		/// <summary>
		/// getProfileValue:: gets the profile value node from the user (or site) profiles (if defined or exists)
		/// </summary>
		private XmlNode getProfileNode(string fldname) {
			XmlNode thisprofile = null;
			if (UserProfile != null)
				thisprofile = UserProfile.Get(fldname);
			if (thisprofile == null && SiteProfile != null)
				thisprofile = SiteProfile.Get(fldname);
			return thisprofile;
		}
		/// <summary>
		/// addSubObjFromProfile:: add subobjs from profile, unless it exists in field
		/// </summary>
		private void addSubObjFromProfile(XmlElement fld) {
			if (fld.SelectSingleNode("subobjs") != null)
				return;
			XmlNode subobjnode = null;
			string subobjsrc = (fld.SelectSingleNode("@subobj") != null)? fld.GetAttribute("subobj") : fld.GetAttribute("name");
			if (UserProfile != null)
				subobjnode = UserProfile.GetSub(subobjsrc);
			if (subobjnode == null && SiteProfile != null)
				subobjnode = SiteProfile.GetSub(subobjsrc);
			if (subobjnode != null)
				fld.AppendChild(fld.OwnerDocument.ImportNode(subobjnode, true));
		}
		#endregion
	}
}
